home *** CD-ROM | disk | FTP | other *** search
/ MacWorld: Complete Mac Interactive / Macworld Complete Mac Interactive CD)(1994).iso / The Best of BMUG / Utilities / Text and Speech / Alpha.5.76 / Tcl / ElectricAlias / electricAlias.tcl
Text File  |  1994-06-28  |  25KB  |  785 lines

  1. # FILE: electricAlias.tcl
  2. #
  3. # LAST UPDATE: 01/25/93 2:41:51 PM
  4. #
  5. # This file contains the following TCL procedures:
  6. #
  7. #   electricAlias-version   -- returns the current version of electricAlias
  8. #   electricAlias-help      -- opens 'electricAlias help' read-only
  9. #   electricAlias-on        -- turns on (enables) electricAlias-insert
  10. #   electricAlias-off       -- turns off (disables) electricAlias-insert
  11. #   electricAlias-mode      -- set/list current electricAlias mode
  12. #   electricAlias-def       -- creates an electricAlias definition
  13. #   electricAlias-var       -- creates an electricAlias variable
  14. #   electricAlias-exists    -- returns true/false 
  15. #   electricAlias-list      -- returns a list of electricAlias definitions
  16. #   electricAlias-names     -- returns a list of active electricAliases
  17. #   electricAlias-idefine   -- interactive define
  18. #   electricAlias-iundefine -- interactive undefine
  19. #   electricAlias-removeall -- removes all electricAlias definitions
  20. #   electricAlias-undefine  -- removes an electricAlias definition
  21. #   electricAlias-insert    -- on-the-fly template insertion (the real guts of this thing) 
  22. #   electricAlias           -- for compatibility with old version
  23. #   getAlias                -- returns a specific current alias definition
  24. #   nextStop                -- finds the next template stop
  25. #   prevStop                -- finds the previous template stop
  26. #   askalias                -- prompts the user for a value to set an alias variable
  27. #   changeMode              -- new version to enable electricAlias (renames old
  28. #                              version to 'original-changeMode')
  29. #
  30. # 'electricAlias-insert' (bound to TAB) provides automatic template/aliasing on the fly.
  31. #
  32. #    For documentation, see 'electricAlias help'. For examples, see 'aliases'. 
  33. #
  34. #    To use, simply place this file place in a folder named $HOME:Tcl:electricAlias:
  35. #    and add 'source $HOME:Tcl:electricAlias:electricAlias.tcl' to AlphaBits.tcl.
  36. #    Also create a folder named $HOME:TCL:electricAlias:Aliases and make sure to place
  37. #    at least a file named 'Aliases' in it with your default aliases.
  38. #    If you wish to use the language extensions feature, place respective
  39. #    files 'Aliases.Tcl', 'Aliases.C', etc.. there as well.
  40. #
  41. # IMPORTANT NOTE
  42. #   *********************************************************************
  43. #   * When changing to a mode for the first time in an Alpha session    *
  44. #   * (e.g. editing a C program), there may be a noticable delay as the *
  45. #   * appropriate aliases are loaded.  This is done rather than loading *
  46. #   * everything at startup to save memory and startup time.  This only *
  47. #   * occurs once per session per mode.                                 *
  48. #   *********************************************************************
  49. #
  50. #
  51. # SEE ALSO unknown.tcl, date.tcl, update.tcl, number.tcl
  52. #
  53. ################################################################################
  54.  
  55. # COPYRIGHT:
  56. #
  57. #    Copyright © 1992,1993 by David C. Black
  58. #    All rights reserved.
  59. #
  60. #    Redistribution and use in source and binary forms are permitted
  61. #    provided that the above copyright notice and this paragraph are
  62. #    duplicated in all such forms and that any documentation,
  63. #    advertising materials, and other materials related to such
  64. #    distribution and use acknowledge that the software was developed
  65. #    by David C. Black.
  66. #
  67. #    THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
  68. #    IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  69. #    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  70. #
  71. ################################################################################
  72.  
  73. # AUTHOR
  74. #
  75. #    David C. Black
  76. #    Internet: black@mpd.tandem.com (preferred)
  77. #    GEnie:    D.C.Black
  78. #    USnail:   6217 John Chisum Lane, Austin, TX 78749
  79. #
  80. ################################################################################
  81.  
  82. # HISTORY
  83. #                  
  84. # modified who rev reason
  85. # -------- --- --- ------ 
  86. # 01/25/93 DCB 1.8 Execute 'activateHook' after loading
  87. #                  Now use electricAlias-changemode instead of original-changemode
  88. # 01/23/93 DCB 1.7 Changed default locations
  89. #                  Split electricAlias into multiple specialized proc's
  90. # 01/06/93 DCB 1.6 Removed electricEnter, date, update, number to
  91. #                  separate .tcl files
  92. #                  Simplified installation
  93. #                  Added weekday, month, day, year to date proc
  94. #                  Fixed electricEnter & §«TCL_COMMAND» to work at global level
  95. #                  Changed bind to TAB
  96. #                  Added electricAlias help sub-command
  97. #                  'delete' now requires MODE
  98. #                  'add' renamed to 'interactive-add'
  99. #                  'remove' renamed to 'interactive-remove'
  100. #                  'list','names' & 'removeall' now allow restriction to a particular mode
  101. #                  'define' & 'variable' now return definition if not provided
  102. #                  Added askalias proc for use in definitions
  103. #                  Added getAlias proc
  104. #                  •-templates now require that they also be at end of line
  105. #                  Corrected \b\b && ^\b substitutions
  106. #                  Modified temporary marks to be window specific
  107. #                  Added 'update' proc
  108. # 11/23/92 DCB 1.5 Included definition of 'nextStop' proc
  109. #                  Changed 'stop's to 'st•p's to avoid collisions with permanent marks
  110. #                  aliasmode is now forced to lowercase
  111. #                  'electricAlias mode' without arg now 'return's the mode
  112. #                  Added 'electricAlias removeall' command
  113. #                  Fixed 'electricAlias list' bug with variables
  114. #                  Nil-mode alias variable now treated as global
  115. #                  Reversed ordering of HISTORY
  116. # 11/18/92 DCB 1.4 'electricAlias mode' now uses/require MODE argument
  117. #                  Modified 'date' proc
  118. # 11/17/92 DCB 1.3 Fixed nasty missing \] in §«TCL_COMMAND»
  119. # 11/16/92 DCB 1.2 Prevent • from appearing in variable mode definitions
  120. #                  §«TCL_COMMAND» now does each invocation separately
  121. #                  §«TCL_COMMAND» now uses [eval]
  122. #                  One minor typo
  123. #                  Non-• templates are now recognized at the beginning of a line
  124. #                  electricEnter now inserts in the correct window
  125. #                  Documented 'date' proc & added 'number' proc (useful in aliases)
  126. #                  Minor comment editing/formatting
  127. # 11/15/92 DCB 1.1 Added {version} command
  128. #                  Code to sub \n for \r in {define} and {variable}
  129. #                  Limit variable substitutions to 99 per template (avoid infinite)
  130. #                  Limit • mode templates to non-nil major modes
  131. #                  Added electric commands §«TCL_COMMAND»
  132. # 11/14/92 DCB 1.0 Original
  133. ################################################################################
  134.  
  135. # DESIGN NOTES
  136. # electricAlias uses a single array ALIAS to store all of its data. Aliases 
  137. # themselves are stored as ALIAS(mode,name). This means that commas are not 
  138. # allowed in mode names (not a severe restriction). State information is 
  139. # stored in ALIAS(name). 
  140. # To make it easier to undo an unintentional template, insertText is called
  141. # once with the normal insertion of a space.  If a template succeeds, then the
  142. # matched word is replaced.  To get back to the plain insertion, just UNDO
  143. # (CMD-Z) twice!  To undo all the way you need one more undo.
  144. #
  145. # Also, if text is selected then the template checking is always abandoned
  146. # in favor of a real space.
  147. # WARNING: If binding to another key is desired, be sure to change the
  148. # definition of $bindKey appropriately.
  149. #
  150. # Use of the bullet (•) to flag stops was arbitrary to some extent.  It had
  151. # to be something easy to use, but not a normal part of programming languages.
  152. # It also needed to be something that would not need special escaping in a
  153. # regular expression.  The same is true for alias variables.
  154. #
  155. ################################################################################
  156.  
  157. # IDEA/REQUEST/TODO
  158. # electricFunc -or- How to recognize procedural definitions on the fly so 
  159. # that later instantiations/calls can automatically insert the correct
  160. # template?  This should be extensible to several languages.
  161. #
  162. # For example in C, I can define 'int max(int a,int b) { return a>b ? a : b }'.
  163. # Later when I type 'x = max(', I would get 'x = max(a,b)' with 'a,b' 
  164. # automatically selected.
  165. # In Verilog, this is complicated by name parameters. For example a definition:
  166. # 'module myAnd (y,a,b); input a,b; output y; assign y = a & b; endmodule'
  167. # should be instantiated with 'myAnd THIS1(.a(a_wire),.b(b_wire));'.
  168. # The justification for the entire electricFunc concept is that frequently
  169. # modules may have literally tens of connections and leaving one out or
  170. # misnaming can be disasterous. The same happens occasionally in C or you
  171. # forget the names of the parameters (more likely).
  172. #
  173. ################################################################################
  174.  
  175. #message "Loading electricAlias.tcl"
  176.  
  177. # Define global array for state/alias data
  178. if {[info exists ALIAS(active)] == 0} {
  179.     if {[info exists ALIAS] == 1} {
  180.         # Its scalar and we need an array
  181.         unset ALIAS
  182.     }
  183.     set ALIAS(active) 1
  184.     set ALIAS(mode)   "tcl"
  185.     set ALIAS(modes)  {tcl,}
  186. }
  187. #
  188. ################################################################################
  189.  
  190. proc electricAlias-version {} {
  191.     return "electricAlias version 1.8"
  192. }
  193. #endproc electricAlias-version
  194. ##############################################################################
  195.  
  196. proc electricAlias-help {} {
  197.     set helpDirs {$HOME:Help $HOME}
  198.     set helpFile "electricAlias Help"
  199.     foreach helpDir $helpDirs{
  200.         if {[file exists $helpDir:$helpFile} {
  201.             edit -r -m $helpDir:$helpFile
  202.             return
  203.         }
  204.     }
  205. }
  206. #endproc electricAlias-help
  207. ##############################################################################
  208.  
  209. proc electricAlias-on {} {
  210.     global ALIAS
  211.     set ALIAS(active) 1
  212. }
  213. #endproc electricAlias-on
  214. ##############################################################################
  215.  
  216. proc electricAlias-off {} {
  217.     global ALIAS
  218.     set ALIAS(active) 0
  219. }
  220. #endproc electricAlias-off
  221. ##############################################################################
  222.  
  223. proc electricAlias-mode {args} {
  224.     global ALIAS
  225.     set argc [llength $args]
  226.     set aliasmode $ALIAS(mode)
  227.     if {$argc > 1} {
  228.         error "Usage: electricAlias-mode ?NAME?"
  229.     }
  230.     if {$argc == 0} {
  231.         return $aliasmode
  232.     }
  233.     set aliasmode [string tolower [lindex $args 0]]
  234.     if {[regexp {[,]} $aliasmode]} {
  235.         error "Alias modes may not include commas"
  236.     }
  237.     set ALIAS(active) 1
  238.     regsub {^•} "$aliasmode" "" aliasmode
  239.     set ALIAS(mode) "$aliasmode"
  240.     if {[lsearch $ALIAS(modes) $aliasmode,] < 0} {
  241.         lappend ALIAS(modes) $aliasmode,
  242.     }
  243.     #message "Aliasmode $aliasmode"    
  244. }
  245. #endproc electricAlias-mode
  246. ##############################################################################
  247.  
  248. proc electricAlias-def {args} {
  249.     global ALIAS
  250.     set aliasmode [string tolower [lindex $args 0]]
  251.     set argc [llength $args]
  252.     if {$argc < 2 || $argc > 3} {
  253.         error "Usage: electricAlias-def MODE NAME ?DEFINITION?"
  254.     }
  255.     set aliasmode [string tolower [lindex $args 0]]
  256.     if {[regexp {[,]} $aliasmode]} {
  257.         error "Alias modes may not include commas"
  258.     }
  259.     set name      [lindex $args 1]
  260.     if {$argc == 2} {
  261.         return [getAlias $aliasmode $name]
  262.     }
  263.     set defn      [lindex $args 2]
  264.     regsub -all "\n" $defn "\r" defn
  265.     set ALIAS($aliasmode,$name) $defn
  266.     if {[lsearch $ALIAS(modes) $aliasmode,] < 0} {
  267.         lappend ALIAS(modes) $aliasmode,
  268.     }
  269. }
  270. #endproc electricAlias-def
  271. ##############################################################################
  272.  
  273. proc electricAlias-var {args} {
  274.     global ALIAS
  275.     set aliasmode [string tolower [lindex $args 0]]
  276.     set argc [llength $args]
  277.     if {$argc < 2 || $argc > 3} {
  278.         error "Usage: electricAlias-var MODE NAME ?DEFINITION?"
  279.     }
  280.     set aliasmode [string tolower [lindex $args 0]]
  281.     if {[regexp {[,]} $aliasmode]} {
  282.         error "Alias modes may not include commas"
  283.     }
  284.     set name      [lindex $args 1]
  285.     if {$argc == 2} {
  286.         return [getAlias $aliasmode $name]
  287.     }
  288.     set defn      [lindex $args 2]
  289.     regsub -all "\n" $defn "\r" defn
  290.     set ALIAS($aliasmode,§\{$name\}) $defn
  291.     if {[lsearch $ALIAS(modes) $aliasmode,] < 0} {
  292.         lappend ALIAS(modes) $aliasmode,
  293.     }
  294. }
  295. #endproc electricAlias-var
  296. ##############################################################################
  297.  
  298. proc electricAlias-exists {args} {
  299.     global ALIAS
  300.     set argc [llength $args]
  301.     if {$argc != 2} {
  302.         error "Usage: electricAlias-exists MODE NAME"
  303.     }
  304.     set aliasmode [string tolower [lindex $args 0]]
  305.     set name [lindex $args 1]
  306.     return [info exists ALIAS($aliasmode,$name)]
  307. }
  308. #endproc electricAlias-exists
  309. ##############################################################################
  310.  
  311. proc electricAlias-list {args} {
  312.     global ALIAS
  313.     set argc [llength $args]
  314.     set aliasmode $ALIAS(mode)
  315.     if {$argc > 1} {
  316.         error "Usage: electricAlias-list ?MODE?"
  317.     }
  318.     if {$argc == 1} {
  319.         set theMode [string tolower [lindex $args 0]]
  320.         if {[regexp {[,]} $theMode]} {
  321.             error "Alias modes may not include commas"
  322.         }
  323.     } else {
  324.         set theMode ""
  325.     }
  326.     set list {}
  327.     set count 1
  328.     foreach name [array names ALIAS] {
  329.         incr count
  330.         set index [split $name ","]
  331.         if {[llength $index] >= 2} {
  332.             set name [join [lrange $index 1 end] ","]
  333.             set aliasmode [lindex $index 0]
  334.             if {$theMode == "" || $aliasmode == $theMode || "$aliasmode" == "•$theMode"} {
  335.                 lappend list [getAlias $aliasmode $name]
  336.             }
  337.         }
  338.     }
  339.     #endforeach
  340.     return [join [lsort $list] "\r"]
  341. }
  342. #endproc electricAlias-list
  343. ##############################################################################
  344.  
  345. proc electricAlias-names {args} {
  346.     global ALIAS
  347.     set argc [llength $args]
  348.     set aliasmode $ALIAS(mode)
  349.     if {$argc > 1} {
  350.         error "Usage: electricAlias-names ?MODE?"
  351.     }
  352.     if {$argc == 1} {
  353.         set theMode [string tolower [lindex $args 0]]
  354.         if {[regexp {[,]} $theMode]} {
  355.             error "Alias modes may not include commas"
  356.         }
  357.     } else {
  358.         set theMode ""
  359.     }
  360.     set list {}
  361.     foreach name [array names ALIAS] {
  362.         set index [split $name ","]
  363.         if {[llength $index] < 2} {
  364.             continue
  365.         }
  366.             if {$theMode == "" || $aliasmode == $theMode || "$aliasmode" == "•$theMode"} {
  367.             lappend list "$name"
  368.         }
  369.     }
  370.     #endforeach
  371.     return [lsort $list]
  372. }
  373. #endproc electricAlias-names
  374. ##############################################################################
  375.  
  376. proc electricAlias-idefine {} {
  377.     global ALIAS
  378.     set aliasmode $ALIAS(mode)
  379.     set list [lsort $ALIAS(modes)]
  380.     catch {set name [eval [concat {prompt "Add mode,name:" "" Modes} $list]]}
  381.     if {[info exists name] == 0} { return }
  382.     if {$name == ""} { return }
  383.     if {[string first $name ","] < 0} {
  384.         set aliasmode [string range $name 0 [expr {$ind-1}]]
  385.         set name "$aliasmode,$name"
  386.     }
  387.     if {$name == ""} { return }
  388.     if {[info exists ALIAS($name)} {
  389.         if {[askyesno "Replace existing definition?"] != "Yes"} { return }
  390.     }
  391.     set defn [prompt "Definition of \"$name\":" ""]
  392.     if {$defn == ""} { return }
  393.     set ALIAS($name) $defn
  394.     message "Defined $name"
  395. }
  396. #endproc electricAlias-idefine
  397. ##############################################################################
  398.  
  399. proc electricAlias-iundefine {} {
  400.     global ALIAS
  401.     set list [electricAlias-names]
  402.     catch {set name [eval [concat {prompt {Remove mode,alias:} [lindex $list 0] Alias} $list]]}
  403.     if {[info exists name]} {
  404.         if {[string first $name ","] >= 0} {
  405.             unset ALIAS($name)
  406.             message "Removed $name"
  407.             unset name
  408.         }
  409.     }
  410. }
  411. #endproc electricAlias-iundefine
  412. ##############################################################################
  413.  
  414. proc electricAlias-removeall {args} {
  415.     global ALIAS
  416.     set argc [llength $args]
  417.     set aliasmode $ALIAS(mode)
  418.     if {$argc > 1} {
  419.         error "Usage: electricAlias-removeall ?MODE?"
  420.     }
  421.     if {$argc == 1} {
  422.         set theMode [string tolower [lindex $args 0]]
  423.         if {[regexp {[,]} $theMode]} {
  424.             error "Alias modes may not include commas"
  425.         }
  426.     } else {
  427.         set theMode ""
  428.     }
  429.     foreach name [array names ALIAS] {
  430.         if {[string first "," $name] >= 0} {
  431.             set aliasmode = [lindex [split $name ","] 0]
  432.             if {$theMode == "" || $aliasmode == $theMode || "$aliasmode" == "•$theMode"} {
  433.                 unset ALIAS($name)
  434.             }
  435.         }
  436.     }
  437.     #endforeach
  438. }
  439. #endproc electricAlias-removeall
  440. ##############################################################################
  441.  
  442. proc electricAlias-undefine {aliasmode name} {
  443.     global ALIAS
  444.     set aliasmode [string tolower $aliasmode]
  445.     if {[regexp {[,]} $aliasmode]} {
  446.         error "Alias modes may not include commas"
  447.     }
  448.     if {[info exists ALIAS($aliasmode,$name)] == 0} {
  449.         error "electricAlias does not exist!"
  450.     }
  451.     unset ALIAS($aliasmode,$name)
  452. }
  453. #endproc electricAlias-undefine
  454. ##############################################################################
  455.  
  456. proc electricAlias-insert {args} {
  457.     global ALIAS
  458.     set aliasmode $ALIAS(mode)
  459.     set bindKey "\t"
  460.     set argc [llength $args]
  461.  
  462.     if {$argc == 0} {
  463.         if {[getSelect]   != "" }  then {
  464.             replaceText [getPos] [selEnd] $bindKey
  465.             forwardChar
  466.             return
  467.         }
  468.         if {$ALIAS(active) == 0} {
  469.             insertText $bindKey
  470.             return
  471.         }
  472.         set match 0
  473.         set args [list normal]
  474.         set pos [getPos]
  475.         set bol [getText [lineStart $pos] $pos]
  476.         set eol [getText [expr {$pos}] [nextLineStart $pos]]
  477.         set modMode ""
  478.         # First token on the line?
  479.         if {! $match } {
  480.             if {[regexp {^([     ]*)([^     ]+)$} $bol all indent name]} {
  481.                 if {[regexp "^\[     \]*\[\r\n\]?\$" $eol all]} {
  482.                     set args [list insert "$indent" "$name"]
  483.                     set modMode "•"
  484.                     set match 1
  485.                 }
  486.             }
  487.         }
  488.  
  489.         # Word token?
  490.         if {! $match && [regexp {([     ]+)([^     ]+)$} "$bol" all indent name] == 1} {
  491.             set args [list insert "" "$name"]
  492.             set match 1
  493.         }
  494.  
  495.         insertText "$bindKey"
  496.     }
  497.  
  498.     set cmnd [lindex $args 0]
  499.     set args [lreplace $args 0 0]
  500.     set argc [llength $args]
  501.  
  502.     if {$cmnd == "normal"} {
  503.         return
  504.     }
  505.  
  506.     set indent [lindex $args 0]
  507.     set name [lindex $args 1]
  508.     set match 0
  509.  
  510.     # • mode template?
  511.     if {$match == 0 && $modMode == "•" && [info exists ALIAS($modMode$aliasmode,$name)] == 1} {
  512.         set defn "$ALIAS($modMode$aliasmode,$name)"
  513.         set match 1
  514.     }
  515.  
  516.     # embedded word template?
  517.     if {$match == 0 && [info exists ALIAS($aliasmode,$name)] == 1} {
  518.         set defn "$ALIAS($aliasmode,$name)"
  519.         set match 2
  520.     }
  521.  
  522.     # nil mode • definition matches everything iff non-nil aliasmode
  523.     if {$match == 0 && $modMode == "•"  && $aliasmode != "" && [info exists ALIAS(•,$name)] == 1} {
  524.         set defn "$ALIAS(•,$name)"
  525.         set match 3
  526.     }
  527.  
  528.     # nil mode matches everything
  529.     if {$match == 0 && [info exists ALIAS(,$name)] == 1} {
  530.         set defn "$ALIAS(,$name)"
  531.         set indent ""
  532.         set match 4
  533.     }
  534.  
  535.     # Next line for debug:
  536.     #message "$modMode $aliasmode $name -> $match"
  537.  
  538.     # return if no aliases found
  539.     if {$match == 0} { 
  540.         return
  541.     }
  542.  
  543.     # Perform substitutions
  544.     set limit 99
  545.     set doAnotherSubstitute 1
  546.     while {$doAnotherSubstitute} {
  547.         set doAnotherSubstitute 0
  548.         # substitute commands §«TCL_COMMAND»
  549.         while {[regexp {§«([^»]+)»} $defn all text] == 1} {
  550.             global _text
  551.             global _returnText
  552.             set _text $text
  553.             set _returnText ""
  554.             set errcode [uplevel #0 {catch $_text _returnText}]
  555.             if {$errcode != 0} {
  556.                 set _returnText "§ERROR $errcode($_text->$_returnText)"
  557.             }
  558.             regsub {§«([^»]+)»} $defn $_returnText defn
  559.             set doAnotherSubstitute 1
  560.             if {[incr limit -1] <= 0} {
  561.                 error "Too many electricAlias command substitutions"
  562.             }
  563.             unset _text
  564.             unset _returnText
  565.         }
  566.         #endwhile substitute cmds
  567.  
  568.         # substitute vars §{NAME}
  569.         while {[regexp {§\{[A-Za-z0-9_-]+\}} $defn var] == 1} {
  570.             if {[info exists ALIAS($aliasmode,$var)] == 1} {
  571.                 set repl $ALIAS($aliasmode,$var)
  572.             } else {
  573.                 # Does a global version of the variable exist?
  574.                 if {[info exists ALIAS(,$var)] == 1} {
  575.                     set repl $ALIAS(,$var)
  576.                 } else {
  577.                     set repl ""
  578.                 }
  579.             }
  580.             regsub -all $var $defn $repl defn
  581.             if {[info exists ALIAS($aliasmode,$var)] == 0 && [info exists ALIAS(,$var)] == 0} {
  582.                 alertnote "No such electricAlias variable $var"
  583.             }
  584.             set doAnotherSubstitute 1
  585.             if {[incr limit -1] <= 0} {
  586.                 alertnote "Too many electricAlias variable substitutions"
  587.             }
  588.         }
  589.         #endwhile substitute vars
  590.     }
  591.     #endwhile
  592.  
  593.     # substitute indents
  594.     regsub -all "\r" "$defn" "\r$indent" defn
  595.     set bs ""
  596.     if {[regexp "^\b+" $defn bs]} {
  597.         regsub "^\b+" "$defn" "" defn
  598.     }
  599.     while {[regsub ".\b" "$defn" "" defn]} {
  600.         ;
  601.     }
  602.     #endwhile
  603.  
  604.     # insert text and set stops
  605.     set repl "$defn"
  606.     regsub -all "•" "$repl" "" repl
  607.     set epos [getPos]
  608.     set bpos [expr {$epos - [string length "$name"] - 1}]
  609.     if {"$repl" == "$defn"} {
  610.         # Assert no stops to mark
  611.         if {$bs == "" && [regexp "\[^\n\r\t \]$" $repl] == 1} {
  612.             append repl " "
  613.         }
  614.         replaceText $bpos $epos "$repl"
  615.         goto [expr {$bpos + [string length "$repl"]}]
  616.         return
  617.     }
  618.     if {$bs != "" && $indent != ""} {
  619.         incr bpos [expr {-[string length $bs]}]
  620.     }
  621.     replaceText $bpos $epos "$repl"
  622.              global stopRing
  623.     set stopRing {}
  624.     set repl "$defn"
  625.     set win [lindex [winNames] 0]
  626.     set i 1
  627.     while {[regexp -indices "•" $repl I] == 1} {
  628.         regsub "•" "$repl" "" repl
  629.         createTMark "${win}•stop$i" [expr {$bpos + [lindex $I 0]}]
  630.         lappend stopRing "${win}•stop$i"
  631.         incr i
  632.     }
  633.     #endwhile
  634.  
  635.     gotoTMark "${win}•stop1"
  636.     bind 'j' <z> nextStop
  637.     bind 'j' <zs> prevStop
  638. }
  639. #endproc electricAlias-insert
  640.  
  641. bind '\t' electricAlias-insert
  642. ################################################################################
  643.  
  644. proc electricAlias {cmnd args} {
  645.     case {[llength $args]} {
  646.       {0} {electricAlias-$cmnd}
  647.       {1} {electricAlias-$cmnd [lindex $args 0]}
  648.       {2} {electricAlias-$cmnd [lindex $args 0] [lindex $args 1]}
  649.       {3} {electricAlias-$cmnd [lindex $args 0] [lindex $args 1] [lindex $args 2]}
  650.     }
  651.     #endcase
  652.     electricAlias-$cmnd $args
  653. }
  654. #endproc electricAlias
  655. ##############################################################################
  656.  
  657.  
  658. proc getAlias {aliasmode name} {
  659.     global ALIAS
  660.     if {![info exists ALIAS($aliasmode,$name)]} {
  661.         alertnote "getAlias: ?$aliasmode $name?"
  662.         return ""
  663.     }
  664.     set repl "$ALIAS($aliasmode,$name)"
  665.  
  666.     regsub -all "\r" "$repl" "\\r" repl
  667.     regsub -all "\n" "$repl" "\\n" repl
  668.     regsub -all "\t" "$repl" "\\t" repl
  669.     regsub -all "\b" "$repl" "\\b" repl
  670.     regsub -all {\$} "$repl" "\\\$" repl
  671.     regsub -all {\{} "$repl" "\\\{" repl
  672.     regsub -all {\}} "$repl" "\\\}" repl
  673.  
  674.     regsub -all {\$} "$name" "\\\$" name
  675.     regsub -all {\{} "$name" "\\\{" name
  676.     regsub -all {\}} "$name" "\\\}" name
  677.     regsub -all {\[} "$name" "\\\[" name
  678.     regsub -all {\]} "$name" "\\\]" name
  679.  
  680.     set cmnd "var"
  681.     if {[regexp {^§\\\{.*\}$} $name] == 0} {
  682.         set cmnd "def"
  683.         set name "\"$name\""
  684.     }
  685.     set fmt "electricAlias-%s %-8s %-10s \{%s\}"
  686.     return [format $fmt $cmnd "\"$aliasmode\"" $name $repl]
  687. }
  688. #endproc getAlias
  689. ################################################################################
  690.  
  691. proc nextStop {} {
  692.     global stopRing
  693.     set first [lindex $stopRing 0]
  694.     set stopRing [lreplace $stopRing 0 0]
  695.     lappend stopRing $first
  696.     set next [lindex $stopRing 0]
  697.     gotoTMark $next
  698.  
  699. }
  700. #endproc nextStop
  701. ################################################################################
  702.  
  703. proc prevStop {} {
  704.     global stopRing
  705.     set end [expr {[llength $stopRing] - 1}]
  706.     set last [lindex $stopRing $end]
  707.     set stopRing [lreplace $stopRing $end $end]
  708.     set stopRing [linsert $stopRing 0 $last]
  709.     gotoTMark $last
  710. }
  711. #endproc prevStop
  712. ################################################################################
  713.  
  714.  
  715. proc askalias {prompt name args} {
  716.     global mode
  717.     set argc [llength $args]
  718.     case $argc {
  719.     0 {
  720.         electricAlias-var $mode $name [prompt $prompt ""]
  721.     }
  722.     1 {
  723.         set default $args
  724.         electricAlias-var $mode $name [prompt $prompt $default]
  725.     }
  726.     {default} {
  727.         set default [lindex $args 0]
  728.         set title [lindex $args 1]
  729.         set list [lrange $args 2 end]
  730.         electricAlias-var $mode $name [prompt $prompt $default $title $list]
  731.     }
  732.     }
  733.     return ""
  734. }
  735. #endproc askalias
  736. ################################################################################
  737.  
  738. if {![file isdirectory "$HOME:TCL:electricAlias:Aliases"]} {
  739.     mkdir $HOME:TCL:electricAlias:Aliases
  740. }
  741.  
  742. if {[file readable "$HOME:TCL:electricAlias:Aliases:Aliases"]} {
  743.     source $HOME:TCL:electricAlias:Aliases:aliases
  744. } else {
  745.     alertnote "No default file $HOME:TCL:electricAlias:Aliases:aliases"
  746. }
  747.  
  748. # NOTE: electricAlias-changeMode is the OLD version
  749. #       It was renamed to prevent collistion with anything else.
  750. #       Due to the way this must work, it seems like the names
  751. #       are backwards.
  752.  
  753. if {[info procs electricAlias-changeMode] != "electricAlias-changeMode"} {
  754.  
  755.     rename changeMode electricAlias-changeMode
  756.  
  757. proc changeMode {newMode} {
  758.     electricAlias-changeMode $newMode
  759.     global mode
  760.     global HOME
  761.     if {![electricAlias-exists "•$mode" "•$mode"] &&
  762.          [file readable "$HOME:TCL:electricAlias:Aliases:aliases.$mode"]} {
  763.         source "$HOME:TCL:electricAlias:Aliases:aliases.$mode"
  764.     }
  765.     electricAlias-mode "$mode"
  766. }
  767. #endproc changeMode
  768.  
  769. }
  770. #endif
  771. ################################################################################
  772.  
  773. set wins [winNames -f]
  774. if {[llength $wins]} {
  775.     activateHook [lindex $wins 0]
  776. }
  777.  
  778. #message ""
  779.